/* 
 * File:   Simplex.h
 * Author: bastian
 *
 * Created on 31 de mayo de 2011, 21:38
 */

#ifndef FRACCIONES_H
#include "Fracciones.h"
#define FRACCIONES_H
#endif

#ifndef MATRICES_H
#include "Matrices.h"
#define MATRICES_H
#endif

#ifndef VARIOS_H
#include "varios.h"
#define VARIOS_H
#endif

#ifndef TABLASIMPLEX_H
#include "TablaSimplex.h"
#define TABLASIMPLEX_H
#endif

#ifndef TPIVOTE_H
#include "TPivote.h"
#define TPIVOTE_H
#endif

#ifndef SIMPLEXPRIMAL_H
#include "SimplexPrimal.h"
#define SIMPLEXPRIMAL_H
#endif

#ifndef SIMPLEXDUAL_H
#include "SimplexDual.h"
#define SIMPLEXDUAL_H
#endif

#ifndef SIMPLEXTX_H
#include "SimplexTX.h"
#define SIMPLEXTX_H
#endif

#ifndef SIMPLEXTC_H
#include "SimplexTC.h"
#define SIMPLEXTC_H
#endif


//Definicion de funciones
void Simplex_TX(TablaSimplex *tabla);
int esSolucionFactible(TablaSimplex *tabla);
int esSolucionInmejorable(TablaSimplex *tabla);
int esSolucionOptima(TablaSimplex * tabla);

//------------------------------------------------------------------------------

void Simplex_TX(TablaSimplex *tabla){
    
    int NoAcotada = 0;
    Matriz_Mostrar(tabla->MatrizAsociada);
    while(esSolucionOptima(tabla)==1){
        //clrscr();
        Primal_setColP(tabla);
        //clrscr();
        Primal_setFilP(tabla);
        
        printf("\nFil,Col --> %i,%i",tabla->FilaPivotePrimal,tabla->ColumnaPivotePrimal);
    		
        if(tabla->ColumnaPivotePrimal==-1 || tabla->FilaPivotePrimal==-1){
            printf("\nNo se puede Continuar.\nSolucion no acotada");
            NoAcotada=1;
            break;
        }
        
        else{ 
            
            printf("\nPivote: ");
            Fraccion_Mostrar(&tabla->MatrizAsociada->elementos[tabla->FilaPivotePrimal][tabla->ColumnaPivotePrimal]);
            printf("\nUbicado en (fila,columna):");
            printf("\n(%i,%i)",tabla->FilaPivotePrimal+1,tabla->ColumnaPivotePrimal+1);
            printf("\n\nHacemos una nueva iteracion");
            getchar();
            TX_Iteracion(tabla, 1);
            //clrscr();
            Matriz_Mostrar(tabla->MatrizAsociada);
            
        }
    }
    
    if(NoAcotada==0){
        //clrscr();
        printf("\n\nSolucion Optima Encontrada!\n\n");
        Matriz_Mostrar(tabla->MatrizAsociada);
    }
    
}

void Simplex_TC(TablaSimplex *tabla){
    
    int NoAcotada = 0;
    //clrscr();
    Matriz_Mostrar(tabla->MatrizAsociada);
    while(esSolucionOptima(tabla)==1){
        //clrscr();
        Primal_setColP(tabla);
        //clrscr();
        Primal_setFilP(tabla);
    		
        if(tabla->ColumnaPivotePrimal==-1 || tabla->FilaPivotePrimal==-1){
            printf("\nNo se puede Continuar.\nSolucion no acotada");
            NoAcotada=1;
            break;
        }
        
        else{ 
            
            printf("\nPivote: ");
            Fraccion_Mostrar(&tabla->MatrizAsociada->elementos[tabla->FilaPivotePrimal][tabla->ColumnaPivotePrimal]);
            printf("\nUbicado en (fila,columna):");
            printf("\n(%i,%i)",tabla->FilaPivotePrimal+1,tabla->ColumnaPivotePrimal+1);
            printf("\n\nHacemos una nueva iteracion");
            getchar();
            TC_Iteracion(tabla, 1);
            //clrscr();
            Matriz_Mostrar(tabla->MatrizAsociada);
            
        }
    }
    
    if(NoAcotada==0){
        //clrscr();
        printf("\n\nSolucion Optima Encontrada!\n\n");
        Matriz_Mostrar(tabla->MatrizAsociada);
    }
}

void Simplex_TC_FaseUno(TablaSimplex *tabla){
    
    int NoAcotada=0;
    
     //clrscr();
    Matriz_Mostrar(tabla->MatrizAsociada);
    
    while(esSolucionInmejorable(tabla)!=0 && Fraccion_esCero(tabla->Z)!=0){
        //clrscr();
        Primal_setColP(tabla);
        //clrscr();
        Primal_setFilP(tabla);
    		
        if(tabla->ColumnaPivotePrimal==-1 || tabla->FilaPivotePrimal==-1){
            printf("\nNo se puede Continuar.\nSolucion no acotada");
            NoAcotada=1;
            break;
        }
        
        else{ 
            
            printf("\nPivote: ");
            Fraccion_Mostrar(&tabla->MatrizAsociada->elementos[tabla->FilaPivotePrimal][tabla->ColumnaPivotePrimal]);
            printf("\nUbicado en (fila,columna):");
            printf("\n(%i,%i)",tabla->FilaPivotePrimal+1,tabla->ColumnaPivotePrimal+1);
            printf("\n\nHacemos una nueva iteracion");
            getchar();
            TC_Iteracion(tabla, 1);
            //clrscr();
            Matriz_Mostrar(tabla->MatrizAsociada);
            
        }
    
    
    
    }
    
    if(NoAcotada==0){
        //clrscr();
        printf("\n\nFin Fase Uno!\n\n");
        Matriz_Mostrar(tabla->MatrizAsociada);
    }
    
    


}

void Simplex_PrimalDual(TablaSimplex *tabla){

    int NoAcotada = 0;
    int Comparacion;
    Fraccion IP,ID,Cero;
    Fraccion_setValue(&Cero,0,1);
    
    //clrscr();
    Matriz_Mostrar(tabla->MatrizAsociada);
    while(esSolucionOptima(tabla)==1){
        
        if(esSolucionInmejorable(tabla)==1){
            //clrscr();
            printf("\nAsignando Pivote Primal");
            Primal_setColP(tabla);
            Primal_setFilP(tabla);
            //clrscr();
            IP=Primal_Impacto(tabla);
        }
        
        else{
            printf("\nNo hay Pivote Primal");
            tabla->FilaPivotePrimal=tabla->ColumnaPivotePrimal=-1;
            IP=Cero;
        }
        
        if(esSolucionFactible(tabla)==1){
            //clrscr();
            printf("\nAsignando Pivote Dual");
            Dual_setFilP(tabla);
            //clrscr();
            Dual_setColP(tabla);
            ID=Dual_Impacto(tabla);
        }
        
        else{
            printf("\nNo hay Pivote Dual");
            tabla->FilaPivoteDual=tabla->ColumnaPivoteDual=-1;
            ID=Cero;
        }
        
        if( (tabla->ColumnaPivotePrimal==-1 || tabla->FilaPivotePrimal==-1) 
                && (tabla->ColumnaPivoteDual==-1 || tabla->FilaPivoteDual==-1)){
            printf("\nNo se puede Continuar.\nSolucion no acotada");
            NoAcotada=1;
            break;
        }
        
        else{ 
            
            Comparacion = Fraccion_Menor(&IP,&ID);
            
            if(Fraccion_esCero(&IP)!=0){
                printf("\nPivote Primal: ");
                Fraccion_Mostrar(&tabla->MatrizAsociada->elementos[tabla->FilaPivotePrimal][tabla->ColumnaPivotePrimal]);
                printf("\nUbicado en (fila,columna):");
                printf("\n(%i,%i)",tabla->FilaPivotePrimal+1,tabla->ColumnaPivotePrimal+1);
                printf("\nImpacto Primal: ");
                Fraccion_Mostrar(&IP);
                getchar();
            }
            
            if(Fraccion_esCero(&ID)!=0){
                printf("\nPivote Dual: ");
                Fraccion_Mostrar(&tabla->MatrizAsociada->elementos[tabla->FilaPivoteDual][tabla->ColumnaPivoteDual]);
                printf("\nUbicado en (fila,columna):");
                printf("\n(%i,%i)",tabla->FilaPivoteDual+1,tabla->ColumnaPivoteDual+1);
                printf("\nImpacto Dual: ");
                Fraccion_Mostrar(&ID);
                getchar();
            }
            
            if(Comparacion == 2){
                printf("\n\nAplicamos Simplex Primal");
                printf("\nPivote: ");
                Fraccion_Mostrar(&tabla->MatrizAsociada->elementos[tabla->FilaPivotePrimal][tabla->ColumnaPivotePrimal]);
                printf("\nUbicado en (fila,columna):");
                printf("\n(%i,%i)",tabla->FilaPivotePrimal+1,tabla->ColumnaPivotePrimal+1);
                TC_Iteracion(tabla, 1);
            
            
            }
            
            else if(Comparacion == 1){
                printf("\n\nAplicamos Simplex Dual");
                printf("\nPivote: ");
                Fraccion_Mostrar(&tabla->MatrizAsociada->elementos[tabla->FilaPivoteDual][tabla->ColumnaPivoteDual]);
                printf("\nUbicado en (fila,columna):");
                printf("\n(%i,%i)",tabla->FilaPivoteDual+1,tabla->ColumnaPivoteDual+1);
                getchar();
                TC_Iteracion(tabla, 2);
            }
            
            //clrscr();
            printf("\n");
            Matriz_Mostrar(tabla->MatrizAsociada);
            
        }
    }
    
    if(NoAcotada==0){
        //clrscr();
        printf("\n\nSolucion Optima Encontrada!\n\n");
        Matriz_Mostrar(tabla->MatrizAsociada);
    }


}


//------------------------------------------------------------------------------

int esSolucionFactible(TablaSimplex *tabla){

    for(int i = 0; i < tabla->Filas-1; i++){
        if(Fraccion_esMenorQueCero(&tabla->Xb[i])==0)
            return 1;
    }
    
    return 0;
}

int esSolucionInmejorable(TablaSimplex *tabla){

    for(int i = 0; i < tabla->Columnas-1; i++){
        if(Fraccion_esMenorQueCero(&tabla->Zj_Cj[i])==0)
            return 1;
    }
    
    return 0;
}

int esSolucionOptima(TablaSimplex * tabla){
    
    if(esSolucionFactible(tabla)==0 && esSolucionInmejorable(tabla)==0)
        return 0;
    
    else
        return 1;

}

